package com.gxuwz.core.dao.impl;

import java.io.Serializable;
import java.lang.reflect.Field;
import java.util.List;
import java.util.function.IntToDoubleFunction;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.orm.hibernate5.HibernateTemplate;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

import com.gxuwz.core.dao.BaseDao;
import com.gxuwz.core.model.Page;
import com.gxuwz.core.util.EntityUtil;



@Repository("baseDao")
public class BaseDaoImpl<T> implements BaseDao<T> {
	

	HibernateTemplate hibernateTemplate;

	public HibernateTemplate getHibernateTemplate() {
		return hibernateTemplate;
	}

	@Autowired
	public void setHibernateTemplate(HibernateTemplate hibernateTemplate) {
		this.hibernateTemplate = hibernateTemplate;
	}

	protected final Log logger = LogFactory.getLog(getClass());

	@Override
	public T save(T entity) {
		try {
			getHibernateTemplate().saveOrUpdate(entity);
		} catch (RuntimeException e) {
			logger.error("save failed", e);
			throw e;
		}
		return entity;
	}

	@Override
	public T merge(T entity) {
		getHibernateTemplate().merge(entity);
		return entity;
	}

	@Override
	public void update(T entity) {
		getHibernateTemplate().update(entity);

	}

	@Override
	public T get(Class<T> clazz, Serializable id) {
		return getHibernateTemplate().get(clazz, id);
	}

	@Override
	public void remove(Class<T> clazz, Serializable id) {
		getHibernateTemplate().delete(get(clazz, id));
	}

	@Override
	public void remove(T entity) {
		getHibernateTemplate().delete(entity);
	}

	/**
	 * 清除指定对象的缓存
	 */
	@Override
	public void evict(T entity) {
		getHibernateTemplate().evict(entity);

	}

	@Override
	public List<T> getAll(String clazz) {
		String sql = "from "+ clazz;
		Object result = getHibernateTemplate().find(sql);
		return (List<T>)result;
	}

	@Override
	public List<T> findByHql(String queryString, Object[] params) {
		return (List<T>)getHibernateTemplate().find(queryString, params);
	}



	@Override
	public void flush() {
		// TODO Auto-generated method stub
		getHibernateTemplate().flush();
	}


	@Override
	public List<T> findByExample(Object exampleEntity) {
		// TODO Auto-generated method stub
		
		return (List<T>) getHibernateTemplate().findByExample(exampleEntity);
	}

	@Override
	public List<T> findByExample(Object exampleEntity, int firstResult,
			int maxResults) {
		// TODO Auto-generated method stub
		
		return (List<T>) getHibernateTemplate().findByExample(exampleEntity, firstResult, maxResults);
	}

	@Override
	public List<T> find(String hql) {
		return (List<T>) getHibernateTemplate().find(hql);
	}

	@Override
	public List<T> findByEntity(T entity) {
		
		StringBuffer hql = new StringBuffer("from ");
		hql.append(entity.getClass().getSimpleName());
		hql.append(" where 1=1 ");
		String[] fieldNames = EntityUtil.getFiledName(entity);
		for(int i=0;i<fieldNames.length;i++){
			Object value = EntityUtil.getFieldValueByName(fieldNames[i],entity);
			if(value != null){
				hql.append(" and ");
				hql.append(fieldNames[i]);
				hql.append(" LIKE '%");
				hql.append(value);
				hql.append("%' ");
			}
		}
		return (List<T>) getHibernateTemplate().find(hql.toString());
	}

	@Override
	public Page getPage(T entity, Integer page, Integer limit) {
		StringBuffer hql = new StringBuffer("from ");
		hql.append(entity.getClass().getSimpleName());
		hql.append(" where 1=1 ");
		String[] fieldNames = EntityUtil.getFiledName(entity);
		for(int i=0;i<fieldNames.length;i++){
			Object value = EntityUtil.getFieldValueByName(fieldNames[i],entity);
			if(value != null){
				hql.append(" and ");
				hql.append(fieldNames[i]);
				hql.append(" LIKE '%");
				hql.append(value);
				hql.append("%' ");
			}
		}
		List list = (List<T>) getHibernateTemplate().find(hql.toString());
		Page pageUtil = new Page();
		pageUtil.setCode(0);
		pageUtil.setCount(list.size());
		if(page == null || limit == null){
			pageUtil.setData(list);
		}else{
			Integer fromIndex = (page-1) * limit;
			Integer toIndex = fromIndex + limit;
			if(toIndex > list.size()){
				toIndex = list.size();
			}
			pageUtil.setData(list.subList(fromIndex, toIndex));
		}
		return pageUtil;
	}





}



